package com.fenqile.pop;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Objects;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fenqile.pop.enums.AdditionalFeatureType;
import com.fenqile.pop.enums.AfterSaleKind;
import com.fenqile.pop.enums.AfterSaleStatus;
import com.fenqile.pop.enums.DeliveryPeriodKind;
import com.fenqile.pop.enums.DeliverySourceKind;
import com.fenqile.pop.enums.FeatureType;
import com.fenqile.pop.enums.MemoType;
import com.fenqile.pop.enums.OrderStatus;
import com.fenqile.pop.enums.ServicePromiseKind;

public class ResultTypeDeserializer extends SimpleModule {
	private static final long serialVersionUID = -5116151551142049342L;
	
	public ResultTypeDeserializer() {
		addDeserializer(Boolean.class, new BooleanDeserializer());
		addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer());
		addDeserializer(FeatureType.class, new FeatureTypeDeserializer());
		addDeserializer(OrderStatus.class, new OrderStatusDeserializer());
		addDeserializer(MemoType.class, new MemoTypeDeserializer());
		addDeserializer(AdditionalFeatureType.class, new AdditionalFeatureTypeDeserializer());
		addDeserializer(ServicePromiseKind.class, new ServicePromiseKindDeserializer());
		addDeserializer(DeliverySourceKind.class, new DeliverySourceKindDeserializer());
		addDeserializer(DeliveryPeriodKind.class, new DeliveryPeriodKindDeserializer());
		addDeserializer(AfterSaleKind.class, new AfterSaleKindDeserializer());
		addDeserializer(AfterSaleStatus.class, new AfterSaleStatusDeserializer());
	}
	
	public static class BooleanDeserializer extends JsonDeserializer<Boolean> {
		
		@Override
		public Boolean deserialize(JsonParser p, DeserializationContext ctxt)
				throws IOException, JsonProcessingException {
			
			String stringValue = p.getValueAsString();
			
			if (Objects.isNull(stringValue) || stringValue.isEmpty())
				return null;
			
			try {
				int intValue = Integer.valueOf(stringValue);
				if (intValue < 1) return false;
				return true;
			} catch (Exception e) {
				if (Objects.equals(stringValue.toLowerCase(), "true"))
					return true;
				else if (Objects.equals(stringValue.toLowerCase(), "false"))
					return false;
				throw new IllegalArgumentException("cannot convert prop [" + p.getCurrentName() + "] value " + stringValue + " to : " + Boolean.class);
			}
			
		}
		
	}
	
	public static class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
		public static final DateTimeFormatter DATETIMEFORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		
		@Override
		public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt)
				throws IOException, JsonProcessingException {
			
			String stringValue = p.getValueAsString();
			
			if (Objects.isNull(stringValue) || stringValue.isEmpty())
				return null;
			return LocalDateTime.parse(stringValue, DATETIMEFORMATTER);
		}
		
	}
	
	public static class OrderStatusDeserializer extends JsonDeserializer<OrderStatus> {

		@Override
		public OrderStatus deserialize(JsonParser p, DeserializationContext ctxt)
				throws IOException, JsonProcessingException {
			
			String stringValue = p.getValueAsString();
			
			for (OrderStatus os : OrderStatus.values())
				if (Objects.equals(os.getName(), stringValue))
					return os;
			throw new IllegalArgumentException("cannot convert prop [" + p.getCurrentName() + "] value " + stringValue + " to : " + OrderStatus.class);
			
		}
		
	}
	
	
	public static class MemoTypeDeserializer extends JsonDeserializer<MemoType> {

		@Override
		public MemoType deserialize(JsonParser p, DeserializationContext ctxt)
				throws IOException, JsonProcessingException {
			
			String stringValue = p.getValueAsString();
			
			for (MemoType ft : MemoType.values()) {
				if (Objects.equals(ft.getName(), stringValue))
					return ft;
			}
			
			throw new IllegalArgumentException("cannot convert prop [" + p.getCurrentName() + "] value " + stringValue + " to : " + MemoType.class);
		}
		
	}
	
	
	public static class FeatureTypeDeserializer extends JsonDeserializer<FeatureType> {

		@Override
		public FeatureType deserialize(JsonParser p, DeserializationContext ctxt)
				throws IOException, JsonProcessingException {
			
			int intValue = p.getValueAsInt();
			
			for (FeatureType ft : FeatureType.values()) {
				if (Objects.equals(ft.intValue(), intValue))
					return ft;
			}
			
			throw new IllegalArgumentException("cannot convert prop [" + p.getCurrentName() + "] value " + intValue + " to : " + FeatureType.class);
		}
		
	}
	
	public static class AdditionalFeatureTypeDeserializer extends JsonDeserializer<AdditionalFeatureType> {

		@Override
		public AdditionalFeatureType deserialize(JsonParser p, DeserializationContext ctxt)
				throws IOException, JsonProcessingException {
			
			int intValue = p.getValueAsInt();
			
			if (Objects.equals(intValue, 0))
				return null;
			
			for (AdditionalFeatureType aft : AdditionalFeatureType.values()) {
				if (Objects.equals(aft.intValue(), intValue))
					return aft;
			}
			
			throw new IllegalArgumentException("cannot convert prop [" + p.getCurrentName() + "] value " + intValue + " to : " + AdditionalFeatureType.class);
		}
		
	}
	
	
	public static class ServicePromiseKindDeserializer extends JsonDeserializer<ServicePromiseKind> {

		@Override
		public ServicePromiseKind deserialize(JsonParser p, DeserializationContext ctxt)
				throws IOException, JsonProcessingException {
			
			String id = p.getValueAsString();
			p.skipChildren();
			
			
			if (Objects.isNull(id) || id.isEmpty())
				return null;
			
			for (ServicePromiseKind spk : ServicePromiseKind.values()) {
				if (Objects.equals(spk.name().toLowerCase(), id))
					return spk;
			}
			
			throw new IllegalArgumentException("cannot convert prop [" + p.getCurrentName() + "] value " + id + " to : " + ServicePromiseKind.class);
		}
		
	}
	
	public static class DeliverySourceKindDeserializer extends JsonDeserializer<DeliverySourceKind> {

		@Override
		public DeliverySourceKind deserialize(JsonParser p, DeserializationContext ctxt)
				throws IOException, JsonProcessingException {
			
			String name = p.getValueAsString();
			
			if (Objects.isNull(name) || name.isEmpty())
				return null;
			
			for (DeliverySourceKind dsk : DeliverySourceKind.values()) {
				if (Objects.equals(dsk.getName(), name))
					return dsk;
			}
			
			throw new IllegalArgumentException("cannot convert prop [" + p.getCurrentName() + "] value " + name + " to : " + DeliverySourceKind.class);
		}
		
	}
	
	
	public static class DeliveryPeriodKindDeserializer extends JsonDeserializer<DeliveryPeriodKind> {

		@Override
		public DeliveryPeriodKind deserialize(JsonParser p, DeserializationContext ctxt)
				throws IOException, JsonProcessingException {
			
			String name = p.getValueAsString();
			
			if (Objects.isNull(name) || name.isEmpty())
				return null;
			
			for (DeliveryPeriodKind dsk : DeliveryPeriodKind.values()) {
				if (Objects.equals(dsk.getName(), name))
					return dsk;
			}
			
			throw new IllegalArgumentException("cannot convert prop [" + p.getCurrentName() + "] value " + name + " to : " + DeliveryPeriodKind.class);
		}
		
	}
	
	
	public static class AfterSaleKindDeserializer extends JsonDeserializer<AfterSaleKind> {

		@Override
		public AfterSaleKind deserialize(JsonParser p, DeserializationContext ctxt)
				throws IOException, JsonProcessingException {
			
			String name = p.getValueAsString();
			
			if (Objects.isNull(name) || name.isEmpty())
				return null;
			
			for (AfterSaleKind dsk : AfterSaleKind.values()) {
				if (Objects.equals(dsk.getName(), name))
					return dsk;
			}
			
			throw new IllegalArgumentException("cannot convert prop [" + p.getCurrentName() + "] value " + name + " to : " + AfterSaleKind.class);
		}
		
	}
	
	
	public static class AfterSaleStatusDeserializer extends JsonDeserializer<AfterSaleStatus> {

		@Override
		public AfterSaleStatus deserialize(JsonParser p, DeserializationContext ctxt)
				throws IOException, JsonProcessingException {
			
			String name = p.getValueAsString();
			
			if (Objects.isNull(name) || name.isEmpty())
				return null;
			
			for (AfterSaleStatus dsk : AfterSaleStatus.values()) {
				if (Objects.equals(dsk.getName(), name))
					return dsk;
			}
			
			throw new IllegalArgumentException("cannot convert prop [" + p.getCurrentName() + "] value " + name + " to : " + AfterSaleStatus.class);
		}
		
	}
	
}
